/**
 * Created by sun on 2015/3/12.
 */
package com.jbm.core.common;

import com.jbm.core.pb.PBIAcross;

import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;

import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.lang.reflect.Method;

public class OHDecoder extends CumulativeProtocolDecoder
{
//    private static final Logger LOGGER = Logger.getLogger(OHDecoder.class);

	private final String charset;

	public OHDecoder(String charset)
	{
		this.charset = charset;
	}

	protected boolean doDecode(IoSession session, IoBuffer in,
							   ProtocolDecoderOutput out) throws Exception
	{
		int protoc_type = Integer.parseInt((String) session.getAttribute("PROTOC_TYPE"));
		if (in.remaining() >= 1)
		{
			in.mark();// 标记当前位置，以便reset

			byte sign = in.get();
			byte pk_type = (byte)(sign&0xf0);

			if ( pk_type == 0 || pk_type == 0x10 ) //server 1.0 support
			{
				in.reset();
				in.mark();

				int len = 0;
				byte[] blen = new byte[4];
				in.get(blen);
				byte type = blen[0];
				type &= 0xf0;
				if (protoc_type == -1)
					session.setAttribute("PROTOC_TYPE", String.valueOf(type));
				len = (int) ((blen[3] & 0xFF)
						| ((blen[2] & 0xFF) << 8)
						| ((blen[1] & 0xFF) << 16)
						| ((blen[0] & 0x0F) << 24));

				if (len > in.remaining())
				{// 如果消息内容不够，则重置，相当于不读取size
					in.reset();
					return false;// 接收新数据，以拼凑成完整数据
				} else
				{
					Object to = null;

					if (type == 0)
					{
						byte[] bbIn = new byte[len];

						in.get(bbIn, 0, len);

						ByteArrayInputStream bais = new ByteArrayInputStream(bbIn);
						ObjectInputStream ois = new ObjectInputStream(bais);
						to = ois.readObject();
					} else if (type == 0x10)
					{
						byte[] bslen = new byte[2];
						in.get(bslen);
						int strlen = ((bslen[1] & 0xFF)
								| ((bslen[0] & 0xFF) << 8));
						byte[] bname = new byte[strlen];
						in.get(bname, 0, strlen);
						String cname = new String(bname, "UTF8");
						String pbname = "com.jbm.jbmsupplier.pb.PB" + cname + "$" + cname;
						Object pbb = null;

						byte[] bbIn = new byte[len - strlen - 2];
						in.get(bbIn, 0, len - strlen - 2);

						if (cname.equals("String"))
						{
							to = new String(bbIn, "UTF8");
						} else
						{
							try
							{
								Method nb = Class.forName(pbname).getMethod("parseFrom", byte[].class);
								pbb = nb.invoke(null, bbIn);
								to = new TransClass().ProtocolBufferToI(pbb);
							} catch (Exception e)
							{
								e.printStackTrace();
							}
						}
					}

					out.write(to);

					if (in.remaining() > 0)
					{// 如果读取内容后还粘了包，就让父类再给一次，进行下一次解析
						// System.out.println("package left="+in.remaining()+" data="+in.toString());
					}
					return true;// 这里有两种情况1：没数据了，那么就结束当前调用，有数据就再次调用
				}
			}else if ( pk_type == 0x20 )
			{
				if (in.remaining()<3)
				{// 如果消息内容不够，则重置，相当于不读取size
					in.reset();
					return false;// 接收新数据，以拼凑成完整数据
				}

				int len = 0;
				byte[] blen = new byte[3];
				in.get(blen);
				len = (int) ((blen[2] & 0xFF)
						| ((blen[1] & 0xFF) << 8)
						| ((blen[0] & 0xFF) << 16));

				if (len > in.remaining())
				{// 如果消息内容不够，则重置，相当于不读取size
					in.reset();
					return false;// 接收新数据，以拼凑成完整数据
				} else
				{
					byte[] pbbuffer = new byte[len];
					in.get(pbbuffer);

					PBIAcross.IAcross iacross = PBIAcross.IAcross.parseFrom(pbbuffer);
					out.write(iacross);

					return true;// 这里有两种情况1：没数据了，那么就结束当前调用，有数据就再次调用
				}
			}
		}
		return false;// 处理成功，让父类进行接收下个包
	}
}
